package cn.com.dhcc.ddi.task.service;

import cn.com.dhcc.app.core.annotation.SiColumn;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.service.BaseService;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.tag.CommonStaticCode;
import cn.com.dhcc.app.core.util.UUIDGenerator;
import cn.com.dhcc.app.pub.core.tag.staticcode.StaticCode;
import cn.com.dhcc.ddi.datasource.vo.TableColVo;
import cn.com.dhcc.ddi.datasource.vo.TableInfoVo;
import cn.com.dhcc.ddi.task.dao.TaskDao;
import cn.com.dhcc.ddi.task.dao.TaskOntimeDao;
import cn.com.dhcc.ddi.task.dao.TaskTabDao;
import cn.com.dhcc.ddi.task.vo.Task;
import cn.com.dhcc.ddi.task.vo.TaskOntime;
import cn.com.dhcc.ddi.task.vo.TaskTab;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @日期：2017/4/17 10:14
 * @作者：张洪涛
 * @版权所有：东华软件
 * @版本：1.0
 */
@Service
public class SettlementService extends BaseService {
    private static Logger logger = Log.getLogger(Log.LOGTYPE.DDI);
    @Autowired
    private TaskDao taskDao;
    @Autowired
    private TaskOntimeDao taskOntimeDao;
    @Autowired
    private TaskTabDao taskTabDao;
    @Autowired
    private TaskTabService taskTabService;

    /**
     * 结算任务
     *
     * @throws ServiceException
     * @throws DaoException
     * 结算 1.获取需要结算的任务，即前一天运行的周期性任务
     * 2.新增出结算一次性任务，复制对应的任务信息，包括数据源、接收节点和表配置 ，通过对频率判断，计算抽取截日期（目前只做间隔）, 任务表增加一个字段，标识出是否为结算任务，用于在抽取数据时，与普通任务区分
     * 3.按正常任务的流程进行发送数据，在抽取时通过判断是否为结算任务 ，分支进行结算功能和抽取数据，满足少干扰普通任务的运行，按普通任务的运行方式控制任务的数据发送 、发送成功和发送失败的处理任务
     */
    public void settlementStrucTasks() throws ServiceException {
        // 获取需要结算的任务.
        try {
            List<Task> settlementStrucSTasks = taskDao.getSettTasks();
            for (Task task : settlementStrucSTasks) {
                createSettOntimeTask(task);
            }
        } catch (DaoException e) {
            throw new ServiceException("结算任务失败", e);
        } catch (ParseException e) {
            logger.error(e);
        }
    }

    /**
     * 创建结算任务
     * @param task
     * @throws DaoException
     * @throws ServiceException
     */
    private void createSettOntimeTask(Task task) throws DaoException,
            ServiceException, ParseException {
        List<TableInfoVo> tasksTables = taskTabService.getListBytaskId(task.getId());
        if (!checkTableDateCol(tasksTables)){
            return;
        }
        // 计算数据抽取数据范围
        Calendar startDate = Calendar.getInstance();
        Date now = new Date();
        startDate.setTime(now);
        startDate.add(Calendar.DAY_OF_MONTH, -1);
        startDate.set(Calendar.HOUR_OF_DAY, 0);
        startDate.set(Calendar.MINUTE, 0);
        startDate.set(Calendar.SECOND, 0);

        Calendar endDate = Calendar.getInstance();
        endDate.setTime(now);
        endDate.add(Calendar.DAY_OF_MONTH, -1);
        endDate.set(Calendar.HOUR_OF_DAY, 23);
        endDate.set(Calendar.MINUTE, 59);
        endDate.set(Calendar.SECOND, 59);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String settDate = sdf.format(startDate.getTime());
        // 新增一次性结算任务
        Task vo = new Task();
        vo.setId(UUIDGenerator.getUUID());
        vo.setTaskName("结算任务("+task.getTaskName() +")  "+settDate);
        vo.setMpId(task.getMpId());
        vo.setDateCategoryId(task.getDateCategoryId());
        vo.setTaskFreqType(StaticCode.TASK_FREQ_TYPE.ONETIME.getCode());
        vo.setStatus(StaticCode.TASK_STATUS.WAIT.getCode());

        vo.setExtrStartTime(startDate.getTime());
        vo.setExtrEndTime(endDate.getTime());

        vo.setIsAtomicity(task.getIsAtomicity());
        vo.setMtime(new Date());
        //标注为结算功能
        vo.setIsSett("1");
        vo.setSettTaskId(task.getId());
        taskDao.insertOrUpdate(vo);

        TaskOntime ontime = new TaskOntime();
        ontime.setId(UUIDGenerator.getUUID());
        ontime.setTaskId(vo.getId());
        ontime.setMtime(new Date());
        ontime.setExecuteType(TaskOntime.EXECUTE_TYPE.IMME.getCode());
        taskOntimeDao.insertOrUpdate(ontime);
        List<TaskTab> tables = taskTabDao.getTaskTabByTaskId(task.getId());
        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (tables != null) {
            for (TaskTab table : tables) {
                TaskTab tab = new TaskTab();
                tab.setId(UUIDGenerator.getUUID());
                tab.setMtime(new Date());
                tab.setTaskId(vo.getId());
                tab.setTableId(table.getTableId());
                tab.setWhereCondition(table.getWhereCondition());
                tab.setTabOrder(table.getTabOrder());
                String startValue = "";
                if(table.getStartValue() != null && !"".equals(table.getStartValue())){
                    Date tableStartValue = sdf.parse(table.getStartValue());
                    Calendar tableStartDate = Calendar.getInstance();
                    tableStartDate.setTime(tableStartValue);

                    if (tableStartDate.compareTo(startDate) <= 0 ){
                        startValue = sdf.format(startDate.getTime());
                    }else{
                        startValue = table.getStartValue();
                    }
                }else{
                    startValue = sdf.format(startDate.getTime());
                }
                String endValue = "";
                if(table.getEndValue() != null && !"".equals(table.getEndValue())){
                    Date tableEndValue = sdf.parse(table.getEndValue());
                    Calendar tableEndDate = Calendar.getInstance();
                    tableEndDate.setTime(tableEndValue);

                    if (tableEndDate.compareTo(endDate) <= 0 ){
                        endValue = table.getEndValue();
                    }else{
                        endValue = sdf.format(endDate.getTime());
                    }
                }else{
                    endValue = sdf.format(endDate.getTime());
                }

                tab.setStartValue(startValue);
                tab.setEndValue(endValue);
                taskTabDao.insertOrUpdate(tab);
            }
        }
    }


    /**
     * 获取增字段
     * @param cols
     * @return
     */
    private TableColVo getIC(List<TableColVo> cols){
        for (TableColVo tabCol : cols) {
            if (tabCol.getIsIc().equals(CommonStaticCode.YESNO.YES.getStatus())){
                return tabCol;
            }
        }
        return null;
    }

    /**
     * 判断任务所有表增量字段是否为时间字段
     * @param tasksTables
     * @return
     */
    private boolean checkTableDateCol(List<TableInfoVo> tasksTables){
        boolean flag = false;
        int timeic = 0;
        for (TableInfoVo tab:tasksTables) {
            TableColVo icCol = getIC(tab.getTableColVos());
            if(icCol != null){
                SiColumn.DB_TYPE_GROUP group = SiColumn.DB_TYPE_GROUP.getTypeGroup(icCol.getColType());
                if (SiColumn.DB_TYPE_GROUP.DATE == group || SiColumn.DB_TYPE_GROUP.TIMESTAMP == group) {
                    timeic++;
                }
            }

        }
        if (timeic == tasksTables.size()){
            flag = true;
        }
        return flag;
    }
}
